package com.baize.filedowndemo.utils

import android.content.*
import android.net.Uri
import android.os.Build
import android.os.IBinder
import android.text.TextUtils
import android.util.Log
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.widget.*
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.baize.filedowndemo.BuildConfig
import com.baize.filedowndemo.R
import com.baize.filedowndemo.autoupdate.UpgradeService
import java.io.File
import kotlin.concurrent.thread

/**
 * Apk版本升级帮助类
 */
class UpgradeHelper(val context: Context) : DefaultLifecycleObserver {
  val DOWNLOADED_APK_KEY = "DOWNLOADED_APK"

  //sharePreferences保存已下载的apk信息
  val sharePreferences: SharedPreferences by lazy {
    context.getSharedPreferences(DOWNLOADED_APK_KEY, Context.MODE_PRIVATE)
  }

  //弹窗UI
  var upgradeDialog: AlertDialog? = null
  var btnUpgrade: TextView? = null          //弹窗按钮
  var tvUpgradeTitle: TextView? = null      //弹窗标题
  var tvUpgradeProgress: TextView? = null   //弹窗进度（文字）
  var upgradeProgress: ProgressBar? = null  //弹窗进度条

  lateinit var downloadBinder: UpgradeService.DownloadBinder
  private var connection: ServiceConnection? = null

  private val upgradeServiceListener by lazy {
    object : UpgradeService.UpgradeServiceListener {
      override fun onProgressChange(progress: Int) {
        tvUpgradeProgress?.text = "${progress}%"
        upgradeProgress?.progress = progress
        Log.i("baize_", "download progress: $progress")
      }

      override fun downloadFinish(isSuccess: Boolean, file: File?, errReason: String?) {
        if (isSuccess && file?.exists() == true) {
          Log.i("baize_", "保存apk名字: $file.name")
          sharePreferences.edit().putString(DOWNLOADED_APK_KEY, file.name).apply()
          installApk(file)
          unBindService()
          if (upgradeDialog != null && upgradeDialog!!.isShowing) {
            upgradeDialog?.dismiss()
            upgradeDialog = null
          }
        } else {
          Log.i("baize_", "更新失败 downloadFinish: $errReason")
          Toast.makeText(context, "更新失败：${errReason}", Toast.LENGTH_SHORT).show()
          if (upgradeDialog != null && upgradeDialog!!.isShowing) {
            btnUpgrade?.visibility = View.VISIBLE
          }
        }
      }
    }
  }

  /**
   * @param version 3.6.5 -> dodo3_6_5.apk
   */
  fun getApkNameByVersionCode(version: String) = """dodo${version.trim().replace(".", "_")}.apk"""

  /**
   * 检查已安装的apk,删除它
   */
  fun checkDeleteCacheApk() {
    val apkName = sharePreferences.getString(DOWNLOADED_APK_KEY, null)
    Log.i("baize_", "拿到apk名字: $apkName")
    val currentApkName = getApkNameByVersionCode(BuildConfig.VERSION_NAME)
    Log.i("baize_", "当前apk版本号:${BuildConfig.VERSION_NAME} apk名：$currentApkName")
    if (apkName != null && apkName == currentApkName) {
      val cacheFile = File(context.cacheDir, apkName)
      if (cacheFile.exists()) {
        thread {
          Log.i("baize_", "删除apk: $apkName")
          cacheFile.delete()
          sharePreferences.edit().remove(DOWNLOADED_APK_KEY).apply()
        }
      }
    }
  }

  /**
   * 提示升级/安装
   * @param version 新版apk的版本号
   * @param upgradeInfo 升级信息
   * @param forceUpgrade 强制升级
   */
  fun checkUpgradeReady(version: String, upgradeInfo: String?, forceUpgrade: Boolean) {
    val apkName = getApkNameByVersionCode(version)
    val apkFile = File(context.cacheDir, apkName)
    createUpgradeDialog(upgradeInfo, forceUpgrade)
    if (apkFile.exists()) {  //已下载好
      tvUpgradeTitle?.text = "已准备好最新版本安装包，是否安装？"
      btnUpgrade?.text = "安装"
      btnUpgrade?.setOnClickListener { installApk(apkFile) }
    } else {
      tvUpgradeTitle?.text = "是否升级到${version}版本？"
      btnUpgrade?.setOnClickListener {
        it.visibility = View.GONE
        startDownload(apkName)
      }
    }
    upgradeDialog?.show()
  }

  private fun createUpgradeDialog(upgradeInfo: String?, forceUpgrade: Boolean) {
    val upgradeView = LayoutInflater.from(context).inflate(R.layout.dialog_version_upgrade, null)
    btnUpgrade = upgradeView.findViewById<Button>(R.id.btn_upgrade)
    tvUpgradeTitle = upgradeView.findViewById<TextView>(R.id.tv_upgrade_title)
    upgradeView.findViewById<ImageView>(R.id.iv_close).setOnClickListener {
      upgradeDialog?.dismiss()
    }
    val tvUpgradeInfo = upgradeView.findViewById<TextView>(R.id.tv_upgrade_info)
    if (!TextUtils.isEmpty(upgradeInfo)) {
      tvUpgradeInfo.setText(upgradeInfo)
      tvUpgradeInfo.visibility = View.VISIBLE
    } else {
      tvUpgradeInfo.visibility = View.GONE
    }
    tvUpgradeProgress = upgradeView.findViewById<TextView>(R.id.tv_upgrade_progress)
    upgradeProgress = upgradeView.findViewById<ProgressBar>(R.id.progressBar)
    val alertDialog = AlertDialog.Builder(context, R.style.Translucent_NoTitle).setView(upgradeView)
      .setOnKeyListener { dialog, keyCode, event -> keyCode == KeyEvent.KEYCODE_BACK }
      .setCancelable(!forceUpgrade)
    upgradeDialog = alertDialog.create()
  }

  /**
   * 开启前台服务下载
   */
  fun startDownload(apkName: String) {
    if (connection == null) {
      connection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder) {
          Log.i("baize_", "onServiceConnected: ")
          downloadBinder = service as UpgradeService.DownloadBinder
          downloadBinder.setUpgradeServiceListener(upgradeServiceListener)
        }

        override fun onServiceDisconnected(name: ComponentName?) {
        }
      }
    }

    val downloadService = Intent(context, UpgradeService::class.java)
    downloadService.putExtra("APK_NAME", apkName)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      context.startForegroundService(downloadService)
    } else {
      context.startService(downloadService)
    }
    context.bindService(downloadService, connection!!, AppCompatActivity.BIND_AUTO_CREATE)
  }

  fun installApk(file: File) {
    try {
      val authority = "${context.packageName}.baizeFileProvider"
      val apkUri = FileProvider.getUriForFile(context, authority, file)
      val intent = Intent(Intent.ACTION_VIEW);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        Log.i("baize_", "installApk: ${apkUri.toString()}")
        intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
      } else {
        Log.i("baize_", "installApk: ${Uri.fromFile(file).toString()}")
        intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive")
      }
      context.startActivity(intent)
    } catch (e: Exception) {
      Log.i("baize_", "installApk: ${e.message}")
    }
  }

  override fun onDestroy(owner: LifecycleOwner) {
    super.onDestroy(owner)
    Log.i("baize_", "UpgradeHelp onDestroy: ")
    unBindService()
  }

  private fun unBindService() {
    connection?.let {
      context.unbindService(it)
      connection = null
    }
  }

}